#include "game.h"
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"

Game::Game() : gameOver(false), score(0), accumulatedTime(0.1f), updateInterval(0.1f) {
    reset();
}

void Game::reset() {
    snake = std::make_unique<Snake>(20, 15);
    food = std::make_unique<Food>();
    gameOver = false;
    score = 0;
    accumulatedTime = 0.0f;
}

void Game::update() {
    if (gameOver) return;

    // 实时检测按键并更新方向
    handleInput();

    // 控制蛇的移动速度
    accumulatedTime += ImGui::GetIO().DeltaTime;
    if (accumulatedTime >= updateInterval) {
        snake->move(snake->getDirectionX(), snake->getDirectionY());
        checkCollisions();
        accumulatedTime = 0.0f;
    }
}

void Game::handleInput() {
    int newDirX = snake->getDirectionX();
    int newDirY = snake->getDirectionY();
    
    // 检测按键输入，使用IsKeyDown提供更流畅的响应
    if (ImGui::IsKeyDown(ImGuiKey_UpArrow)) {
        newDirY = -1;
        newDirX = 0;
    }
    else if (ImGui::IsKeyDown(ImGuiKey_DownArrow)) {
        newDirY = 1;
        newDirX = 0;
    }
    else if (ImGui::IsKeyDown(ImGuiKey_LeftArrow)) {
        newDirX = -1;
        newDirY = 0;
    }
    else if (ImGui::IsKeyDown(ImGuiKey_RightArrow)) {
        newDirX = 1;
        newDirY = 0;
    }
    else if (newDirX == 0 && newDirY == 0) {
        // 如果是初始状态（没有方向），设置默认向右运动
        newDirX = 1;
    }

    // 防止180度转向
    if ((newDirX != 0 && newDirX == -snake->getDirectionX()) ||
        (newDirY != 0 && newDirY == -snake->getDirectionY())) {
        return;
    }

    // 只更新方向，不立即移动
    snake->setDirection(newDirX, newDirY);
}

void Game::checkCollisions() {
    if (snake->checkCollision() || snake->checkSelfCollision()) {
        gameOver = true;
        return;
    }

    if (snake->getHead() == food->getPosition()) {
        snake->grow();
        food->spawn();
        score += 10;
    }
}

void Game::render() {
    ImGui::SetNextWindowPos(ImVec2(0, 0));
    ImGui::SetNextWindowSize(ImGui::GetIO().DisplaySize);
    ImGui::Begin("Snake Game", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove);

    if (!gameOver) {
        renderGame();
    } else {
        renderGameOver();
    }

    renderUI();
    ImGui::End();
}

void Game::renderGame() {
    ImDrawList* draw_list = ImGui::GetWindowDrawList();
    const float cellSize = 20.0f;
    const ImVec2 boardPos = ImGui::GetCursorScreenPos();

    // Draw grid
    for (int x = 0; x <= 40; x++) {
        draw_list->AddLine(
            ImVec2(boardPos.x + x * cellSize, boardPos.y),
            ImVec2(boardPos.x + x * cellSize, boardPos.y + 30 * cellSize),
            IM_COL32(50, 50, 50, 255));
    }
    for (int y = 0; y <= 30; y++) {
        draw_list->AddLine(
            ImVec2(boardPos.x, boardPos.y + y * cellSize),
            ImVec2(boardPos.x + 40 * cellSize, boardPos.y + y * cellSize),
            IM_COL32(50, 50, 50, 255));
    }

    // Draw snake
    for (const auto& segment : snake->getBody()) {
        draw_list->AddRectFilled(
            ImVec2(boardPos.x + segment.first * cellSize, boardPos.y + segment.second * cellSize),
            ImVec2(boardPos.x + (segment.first + 1) * cellSize, boardPos.y + (segment.second + 1) * cellSize),
            IM_COL32(0, 255, 0, 255));
    }

    // Draw food
    auto foodPos = food->getPosition();
    draw_list->AddRectFilled(
        ImVec2(boardPos.x + foodPos.first * cellSize, boardPos.y + foodPos.second * cellSize),
        ImVec2(boardPos.x + (foodPos.first + 1) * cellSize, boardPos.y + (foodPos.second + 1) * cellSize),
        IM_COL32(255, 0, 0, 255));
}

void Game::renderGameOver() {
    ImGui::SetCursorPos(ImVec2(ImGui::GetWindowSize().x * 0.5f - 100, ImGui::GetWindowSize().y * 0.5f - 50));
    ImGui::Text("Game Over!");
    ImGui::SetCursorPos(ImVec2(ImGui::GetWindowSize().x * 0.5f - 100, ImGui::GetWindowSize().y * 0.5f));
    ImGui::Text("Final Score: %d", score);
    ImGui::SetCursorPos(ImVec2(ImGui::GetWindowSize().x * 0.5f - 100, ImGui::GetWindowSize().y * 0.5f + 50));
    if (ImGui::Button("Restart")) {
        reset();
    }
}

void Game::renderUI() {
    ImGui::SetCursorPos(ImVec2(10, ImGui::GetWindowSize().y - 30));
    ImGui::Text("Score: %d", score);
}